package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.team.TeamUserHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductionOrderErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.BomProductEntity;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.dictionary.ProductionOrderStatusEnum;
import com.xbongbong.saas.enums.product.ProductionOrderFinishProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderMaterielProductEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.BomProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.util.ValidateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("productionOrderAnalyticalServiceImpl")
public class ProductionOrderValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ProductionOrderValidateAnalyticalServiceImpl.class);
    
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private ProductModel productModel;
    @Resource
    private BomProductModel bomProductModel;
    @Resource
    private SaasProductHelp saasProductHelp;
    @Resource
    private TeamUserHelp teamUserHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        teamUserHelp.beforeVerifyUserTeam(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        try {
            JSONObject data = validateDataDTO.getData();
            String corpid = validateDataDTO.getCorpid();
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            Map<String, FieldAttrEntity> explainMap = validateDataDTO.getExplainMap();
            SaveFormatHelp.formatLinkBusiness4Save(data, ProductionOrderEnum.BOM_ID.getAttr(), ProductionOrderEnum.BOM_ID_LINK_TEXT.getAttr(), ProductionOrderEnum.BOM_ID.getFieldType());
            SaveFormatHelp.formatLinkBusiness4Save(data, ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr(), ProductionOrderEnum.INTO_WAREHOUSE_ID_LINK_TEXT.getAttr(), ProductionOrderEnum.INTO_WAREHOUSE_ID.getFieldType());
            SaveFormatHelp.formatLinkBusiness4Save(data, ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr(), ProductionOrderEnum.OUT_WAREHOUSE_ID_LINK_TEXT.getAttr(), ProductionOrderEnum.OUT_WAREHOUSE_ID.getFieldType());

            FieldAttrEntity sheetNo = explainMap.getOrDefault(ProductionOrderEnum.SHEET_NO.getAttr(), fieldAttrEntity);
            // 校验编号长度不超过100且编号存在
            if (Objects.nonNull(sheetNo) && Objects.equals(sheetNo.getStrictController(), BasicConstant.ZERO)) {
                ValidateUtil.checkSerialNumber(validateDataDTO.getSerialNo(), Objects.toString(sheetNo.getAttrName(), ""));
            }
            FieldAttrEntity memoField = explainMap.getOrDefault(ProductionOrderEnum.MEMO.getAttr(), fieldAttrEntity);
            // 校验备注长度
            ValidateUtil.checkFieldEntityLength(data, ProductionOrderEnum.MEMO.getAttr(), Objects.toString(memoField.getAttrName(), ""), AttrLenthConstant.MEMO_MAX_LENGTH);
            Long id = validateDataDTO.getDataId();
            boolean isNew = analyticalHelp.isNew(validateDataDTO.getDataId(), validateDataDTO.getTaskId(), validateDataDTO.getCorpid());
            if (id == null || id < 1) {
                // 新建，状态为未完成
                data.put(ProductionOrderEnum.STATUS.getAttr(), ProductionOrderStatusEnum.UNFINISHED.getCode());
            }

            Boolean productCanSee = true;
            Boolean materielCanSee = true;
            if (!isNew) {
                productCanSee = commonHelp.attrCanSee(validateDataDTO.getExplainMap().get(ProductionOrderEnum.PRODUCT.getAttr()),validateDataDTO.getDataId(),validateDataDTO.getCreatorId(),validateDataDTO.getLoginUser(),validateDataDTO.getCorpid(),XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
                materielCanSee = commonHelp.attrCanSee(validateDataDTO.getExplainMap().get(ProductionOrderEnum.MATERIEL.getAttr()),validateDataDTO.getDataId(),validateDataDTO.getCreatorId(),validateDataDTO.getLoginUser(),validateDataDTO.getCorpid(),XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
            }
            validateDataProduct(data,corpid,id,isNew,productCanSee,materielCanSee);
            if (Objects.isNull(validateDataDTO.getDataId()) || Objects.equals(validateDataDTO.getDataId(), 0L)){
                data.put(ProductionOrderEnum.PRODUCT_UNINSTOCK_NUM.getAttr(),data.get(ProductionOrderEnum.PRODUCT_NUM.getAttr()));
            }
            for (Map.Entry<String, Object> entry : SaasDataInitHelp.initProductionOrder().entrySet()) {
                SaasDataInitHelp.antDataSet(data, entry.getKey(), entry.getValue());
            }
            validateDataDTO.setData(data);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("productionOrderAnalyticalServiceImpl.beforeSave error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    private void validateDataProduct(JSONObject data, String corpid, Long id, boolean isNew, Boolean productCanSee, Boolean materielCanSee) throws XbbException {
        JSONArray productArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,ProductionOrderEnum.PRODUCT.getAttr(),new JSONArray());
        JSONArray materielProductarray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,ProductionOrderEnum.MATERIEL.getAttr(),new JSONArray());
        Long bomId = data.getLong(ProductionOrderEnum.BOM_ID.getAttr());
        Set<Long> pageProductIds = new HashSet<>();
        Map<Long, Double> lossRateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (isNew || productCanSee) {
            if (productArray.size() > 1) {
                throw new XbbException(ProductionOrderErrorCodeEnum.API_ERROR_243039);
            }
            List<BomProductEntity> bomProductList = bomProductModel.getProductsByBomId(bomId, corpid, null);
            List<Long> finishProductIdList = new ArrayList<>();
            List<Long> materialProductIdList = new ArrayList<>();
            for (BomProductEntity bomProductEntity : bomProductList) {
                Long productId = bomProductEntity.getProductId();
                if (Objects.equals(bomProductEntity.getType(), 1)) {
                    finishProductIdList.add(productId);
                } else {
                    materialProductIdList.add(productId);
                    lossRateMap.put(bomProductEntity.getProductId(), bomProductEntity.getAttritionRate());
                }
            }
            List<Long> productionMaterialProductIdList = new ArrayList<>();
            for (Object obj : materielProductarray) {
                JSONObject json = JSONObject.parseObject(obj.toString());
                Long productId = json.getLong(SelectProductEnum.PRODUCT.getAttr());
                pageProductIds.add(productId);
                productionMaterialProductIdList.add(productId);
            }
            if (!(Objects.equals(productionMaterialProductIdList.size(), materialProductIdList.size()) && materialProductIdList.containsAll(productionMaterialProductIdList))) {
                throw new XbbException(ProductionOrderErrorCodeEnum.API_ERROR_243038);
            }
            JSONObject json = productArray.getJSONObject(0);
            Long productId = json.getLong(SelectProductEnum.PRODUCT.getAttr());
            if (!finishProductIdList.contains(productId)) {
                throw new XbbException(ProductionOrderErrorCodeEnum.API_ERROR_243037);
            }
            pageProductIds.add(productId);
            ProductEntityExt productEntityExt = productModel.getByKey(productId, corpid);
            JSONObject productData = productEntityExt.getData();
            String productName = productData.getString(ProductEnum.NAME.getAttr());
            productName = productName == null ? "" : productName;
            String productNo = productEntityExt.getSerialNo();
            productNo = productNo == null ? "" : productNo;
            data.put(ProductionOrderEnum.PRODUCT_NAME.getAttr(), productId);
            data.put(ProductionOrderEnum.PRODUCT_NAME_HIDE.getAttr(), productName);
            data.put(ProductionOrderEnum.PRODUCT_NO.getAttr(), productNo);
            data.put(ProductionOrderEnum.PRODUCT_NUM.getAttr(), json.getDouble(ProductionOrderFinishProductEnum.NUM.getAttr()));
        }else {
            List<BomProductEntity> bomProductList = bomProductModel.getProductsByBomId(bomId, corpid, null);
            for (BomProductEntity bomProductEntity : bomProductList) {
                if (Objects.equals(bomProductEntity.getType(), 2)) {
                    lossRateMap.put(bomProductEntity.getProductId(), bomProductEntity.getAttritionRate());
                }
            }
        }

        if (isNew || materielCanSee) {
            JSONArray jsonArray = new JSONArray();
            for (int i = 0; i < materielProductarray.size(); i++) {
                JSONObject materialJson = materielProductarray.getJSONObject(i);
                Long materialProductId = materialJson.getLong(SelectProductEnum.PRODUCT.getAttr());
                Double lossRate = materialJson.getDouble(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr());
                if (Objects.isNull(lossRate) || Objects.equals(lossRate, 0D)) {
                    materialJson.put(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr(), lossRateMap.getOrDefault(materialProductId,0D));
                }
                SaveFormatHelp.formatLinkBusiness4Save(materialJson,SelectProductEnum.WAREHOUSE.getAttr(),"warehouseName", FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
                jsonArray.add(materialJson);
            }
            if (!jsonArray.isEmpty()) {
                saasProductHelp.productWarehouseExit(corpid, jsonArray);
            }
        }
        saasProductHelp.productExit(corpid,new ArrayList<>(pageProductIds));
    }
}
